<template>
	<view>
		<view>
			<view style="color:#00e">
				<!-- v-if="equipment.length > 0" > -->
				{{
					(equipment.length <= 0?
						'未连接设备':
						((connected ? '已连接设备' : '已选择设备') +
							' : ' +
							equipment[0].name +
							' (' +
							equipment[0].deviceId +
							')')
					)
			}}
			</view>
		</view>
		<view class="view-image">
			<image class="image" :src="imgSrcBot[connected?0:1]"></image>
			<view v-if="connected">
				<image class="image" id="image2" :src="imgSrcFire[fireAni?0:1]" height="50rpx"></image>
				<view :style="intervalID?'color:#f00':'color:#00f'">{{txtAnimate}}　{{intervalID?"正在加热":"保温中"}}　{{txtAnimate}}</view>
			</view>
			<!-- </view> -->
			<view v-if="connected">
				<!-- <view class="view-slider"> -->
				<text space="ensp">当前温度：{{currentTemp}}°C</text>
				<!-- <progress :percent="currentTemp" style="-webkit-flex: 1;flex: 1;"></progress> -->
				<!-- <slider block-size="18" style="-webkit-flex: 1;flex: 1;" min="0" max="100" :value="currentTemp"></slider> -->
				<!-- </view> -->
				<!-- <view class="view-slider"> -->
				<view>设定温度：{{setTemp}}°C</view>
				<slider block-size="18" style="-webkit-flex: 1;flex: 1;" min="20" max="50" :value="setTemp" @changing="changeTemp"
				 @change="selectTemp"></slider>
			</view>
		</view>

		<view class="view-button">
			<button @click="chooseBluetooth">选择蓝牙设备</button>
			<button>帮助</button>
		</view>


		<!-- 遮罩 -->
		<view v-if="maskShow" class="uni-mask" @touchmove.stop.prevent="moveHandle" @click="maskclose">
			<scroll-view class="uni-scroll_box" scroll-y @touchmove.stop.prevent="moveHandle" @click.stop="moveHandle">
				<view class="uni-title">
					已经发现{{ list.length }}{{ showMaskType === 'device' ? '台设备' : '个服务' }}:
				</view>
				<view class="uni-list-box" v-for="(item, index) in list" :key="index" @click="tapQuery(item)">
					<view v-if="showMaskType === 'device'">
						<view class="uni-list_name">{{ item.name || item.localName }}</view>
						<view class="uni-list_item">信号强度:{{ item.RSSI }}dBm</view>
						<view class="uni-list_item">MAC:{{ item.deviceId }}</view>
						<!-- <view class="list-item" v-if="showMaskType === 'device'">
							Service数量:{{ item.advertisServiceUUIDs.length }}
						</view> -->
					</view>
					<view v-if="showMaskType === 'service'">
						<view class="uni-list_item" style="line-height:2.2;">
							UUID: {{ item.uuid }}
							<text v-if="showMaskType === 'service'">
								{{ item.isPrimary ? '（主服务）' : '' }}
							</text>
						</view>
					</view>
					<view v-if="showMaskType === 'characteristics'">
						<view class="uni-list_name">uuid:{{ item.uuid }}</view>
						<view class="uni-list_item">是否支持 read 操作:{{ item.properties.read }}</view>
						<view class="uni-list_item">
							是否支持 write 操作:{{ item.properties.write }}
						</view>
						<view class="uni-list_item">
							是否支持 notify 操作:{{ item.properties.notify }}
						</view>
						<view class="uni-list_item">
							是否支持 indicate 操作:{{ item.properties.indicate }}
						</view>
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				bleMacAddr: "20:04:13:23:1A:62",
				sUUID: "ffe0-0000-1000-8000-00805f9b34fb",
				cUUID: "ffe1-0000-1000-8000-00805f9b34fb",
				handShakeSetp: 0, //0:disconnect, 1:BLE connected, 2:UUID匹配, 3:密码匹配-握手成功
				handShakeCount: 0, //握手失败计数
				maskShow: false,
				showMaskType: 'device',
				connected: false,
				fired: false, //是否在加热
				fireAni: false,
				sliderChanging: false,
				isStop: true,
				intervalID: 0,
				currentTemp: 30, //当前温度
				setTemp: 30, //设定温度
				imgSrcBot: ["../../static/wine_e.png", "../../static/wine_d.png"],
				imgSrcFire: ["../../static/fire_e.png", "../../static/fire_d.png"],
				txtAnimate: "",
				txtAnis: ["-", "\\", "|", "/"],
				list: [],
				equipment: [],
				servicesData: [],
				characteristicsData: [],
				valueChangeData: {},
				adapterState: {
					discovering: false,
					available: false,
				}
			}
		},

		onLoad: function() {
			// this.startBlueTooth();
			this.openBluetoothAdapter();
			// this.onBLEConnectionStateChange();
		},

		methods: {
			changeTemp(e) {
				this.sliderChanging = true;
				this.setTemp = e.detail.value;
			},
			selectTemp(e) {
				if (this.connected) {
					this.setTemp = e.detail.value;
					this.writeAData("=" + this.setTemp + "\r\n");
					setTimeout(() => {
						this.sliderChanging = false;
					}, 1000);
				}
			},

			moveHandle() {},
			/**
			 * 关闭遮罩
			 */
			maskclose() {
				this.maskShow = false;
			},
			
			chooseBluetooth: function() {
				if (this.equipment.length > 0) this.closeBLEConnection();
				this.startBluetoothDevicesDiscovery();
			},
			/**
			 * 选择设备
			 */
			queryDevices() {
				// this.newDeviceLoad = true;
				this.showMaskType = 'device';
				// this.maskShow = true;
				// console.log(this.list);
			},
			tapQuery(item) {
				if (this.showMaskType === 'device') {
					// this.$set(this.disabled, 4, false);
					if (this.equipment.length > 0) {
						this.equipment[0] = item;
					} else {
						this.equipment.push(item);
					}
					console.log(this.equipment);
					this.createBLEConnection();
					// this.newDeviceLoad = false;
				}
				// if (this.showMaskType === 'service') {
				// 	this.$set(this.disabled, 6, false);
				// 	if (this.servicesData.length > 0) {
				// 		this.servicesData[0] = item;
				// 	} else {
				// 		this.servicesData.push(item);
				// 	}
				// }
				// if (this.showMaskType === 'characteristics') {
				// 	this.$set(this.disabled, 7, false);
				// 	if (this.characteristicsData.length > 0) {
				// 		this.characteristicsData[0] = item;
				// 	} else {
				// 		this.characteristicsData.push(item);
				// 	}
				// }
				this.maskShow = false;
			},
			openBluetoothAdapter: function() {
				uni.openBluetoothAdapter({
					success: e => {
						console.log('初始化蓝牙成功:' + e.errMsg);
						console.log(JSON.stringify(e));
						this.isStop = false;
						// this.$set(this.disabled, 0, true);
						// this.$set(this.disabled, 1, false);
						// this.$set(this.disabled, 10, false);
						this.getBluetoothAdapterState();
					},
					fail: e => {
						console.log(e)
						console.log('初始化蓝牙失败，错误码：' + (e.errCode || e.errMsg));
						if (e.errCode !== 0) {
							initTypes(e.errCode, e.errMsg);
						}
					}
				});
			},
			/**
			 * 获取本机蓝牙适配器状态
			 */
			getBluetoothAdapterState: function() {
				uni.getBluetoothAdapterState({
					success: res => {
						console.log(JSON.stringify(res));
						this.adapterState = res;
						// 如果有上次存储的蓝牙设备，连接它
						let saved ={}
						saved.deviceId = this.loadStorage('Id');
						if(saved.deviceId){
							saved.name = this.loadStorage('Name');
							console.log("saved : "+saved);
							this.equipment.push(saved);
							this.createBLEConnection();
						}else
							this.startBluetoothDevicesDiscovery();
					},
					fail: e => {
						console.log('获取本机蓝牙适配器状态失败，错误码：' + e.errCode);
						if (e.errCode !== 0) {
							initTypes(e.errCode);
						}
					}
				});
			},
			/**
			 * 开始搜索蓝牙设备
			 */
			startBluetoothDevicesDiscovery() {
				uni.startBluetoothDevicesDiscovery({
					// services: ['FFE0'],
					success: e => {
						this.maskShow = true;
						console.log('开始搜索蓝牙设备:' + e.errMsg);
						// this.searchLoad = true;
						// this.$set(this.disabled, 1, true);
						// this.$set(this.disabled, 2, false);
						// this.$set(this.disabled, 3, false);
						this.onBluetoothDeviceFound();
					},
					fail: e => {
						console.log('搜索蓝牙设备失败，错误码：' + e.errCode);
						if (e.errCode !== 0) {
							initTypes(e.errCode);
						}
					}
				});
			},
			/**
			 * 发现外围设备
			 */
			onBluetoothDeviceFound() {
				uni.onBluetoothDeviceFound(devices => {
					console.log('开始监听寻找到新设备的事件');
					// this.$set(this.disabled, 3, false);
					this.getBluetoothDevices();
				});
			},
			/**
			 * 获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。
			 */
			getBluetoothDevices() {
				uni.getBluetoothDevices({
					success: res => {
						// this.newDeviceLoad = false;
						console.log('获取蓝牙设备成功:' + res.errMsg);
						// console.log(JSON.stringify(res))
						this.list = res.devices;
						// 选择蓝牙设备
						this.queryDevices();
					},
					fail: e => {
						console.log('获取蓝牙设备错误，错误码：' + e.errCode);
						if (e.errCode !== 0) {
							initTypes(e.errCode);
						}
					}
				});
			},
			/**
			 * 连接低功耗蓝牙
			 */
			createBLEConnection() {
				let deviceId = this.equipment[0].deviceId;
				uni.showToast({
					title: '连接蓝牙...',
					icon: 'loading',
					duration: 99999
				});
				uni.createBLEConnection({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId,
					success: res => {
						console.log(res);
						console.log('连接蓝牙成功:' + res.errMsg);
						// 连接设备后断开搜索 并且不能搜索设备
						this.stopBluetoothDevicesDiscovery(true);
						//创建BLE连接成功后，测试设备是否为指定的单片机蓝牙设备
						this.handShakeSetp = 1; //1:已连接
						uni.hideToast();
						uni.showToast({
							title: '连接成功',
							icon: 'success',
							duration: 2000
						});
						this.readBLECharacteristicValue();
						// this.connected = true;
					},
					fail: e => {
						console.log('连接低功耗蓝牙失败，错误码：' + e.errCode);
						if (e.errCode !== 0) {
							initTypes(e.errCode);
						}
						this.stopBluetoothDevicesDiscovery(true);
						this.connected = false;
						this.handShakeSetp = 0;
						uni.hideToast();
						this.closeBLEConnection();
					}
				});
			},
			/**
			 * 停止搜索蓝牙设备
			 */
			stopBluetoothDevicesDiscovery(types) {
				uni.stopBluetoothDevicesDiscovery({
					success: e => {
						console.log('停止搜索蓝牙设备:' + e.errMsg);
						// if (types) {
						// 	this.$set(this.disabled, 1, true);
						// } else {
						// 	this.$set(this.disabled, 1, false);
						// }
						// this.$set(this.disabled, 2, true);
						// // this.$set(this.disabled, 3, true);
						// this.searchLoad = false;
					},
					fail: e => {
						console.log('停止搜索蓝牙设备失败，错误码：' + e.errCode);
						if (e.errCode !== 0) {
							initTypes(e.errCode);
						}
					}
				});
			},

			/**
			 * 断开与低功耗蓝牙设备的连接
			 */
			closeBLEConnection() {
				let deviceId = this.equipment[0].deviceId;
				uni.closeBLEConnection({
					deviceId,
					success: res => {
						console.log(res);
						console.log('断开低功耗蓝牙成功:' + res.errMsg);
						// this.$set(this.disabled, 1, false);
						// this.$set(this.disabled, 3, true);
						// this.$set(this.disabled, 4, true);
						// this.$set(this.disabled, 5, true);
						// this.$set(this.disabled, 6, true);
						// this.$set(this.disabled, 7, true);
						// this.$set(this.disabled, 8, true);
						// this.$set(this.disabled, 9, true);
						this.connected = false;
						this.equipment = [];
						// this.servicesData = [];
						// this.characteristicsData = [];
					},
					fail: e => {
						console.log('断开低功耗蓝牙成功，错误码：' + e.errCode);
						if (e.errCode !== 0) {
							initTypes(e.errCode);
						}
					}
				});
			},
			writeAData(datas) {
				let deviceId = this.equipment[0].deviceId;
				let serviceId = this.sUUID;
				let characteristicId = this.cUUID;
				const buffer = new ArrayBuffer(datas.length);
				const dataView = new DataView(buffer);
				for (let i = 0; i < datas.length; i++) {
					dataView.setUint8(i, datas[i].charCodeAt());
					// console.log(datas[i].charCodeAt());
				}
				// console.log("buffer----> "+datas+" : "+JSON.stringify(dataView));
				uni.writeBLECharacteristicValue({
					// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
					deviceId,
					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId,
					// 这里的value是ArrayBuffer类型
					value: buffer,
					success(res) {
						console.log('writeBLECharacteristicValue success', res.errMsg)
					}
				})
			},
			/**
			 * 读取低功耗蓝牙设备的特征值的二进制数据值。注意：必须设备的特征值支持 read 才可以成功调用
			 */
			readBLECharacteristicValue() {
				let deviceId = this.equipment[0].deviceId;
				let serviceId = this.sUUID;
				let characteristicId = this.cUUID;
				// console.log(deviceId);
				// console.log(serviceId);
				// console.log(characteristicId);

				this.onBLECharacteristicValueChange();
				// this.onBLECharacteristicValueChange();
				uni.readBLECharacteristicValue({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId,
					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId,
					success: res => {
						// console.log('读取设备数据值成功');
						// console.log(JSON.stringify(res));
						this.notifyBLECharacteristicValueChange();
						this.handShakeSetp = 2; //读取设备服务uuid成功
						this.handShakeCount = 0;
						// this.writeAData("+123456\r\n");
					},
					fail(e) {
						this.handShakeSetp = 0; //握手状态归零
						this.connected = false;
						console.log('读取设备数据值失败，错误码：' + e.errCode);
						if (e.errCode !== 0) {
							initTypes(e.errCode);
						}
					}
				});
			},
			// ArrayBuffer转16进度字符串示例
			ab2hex(buffer) {
				const hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return String.fromCharCode(bit); //(bit.toString()).slice(-1)
					}
				)
				return hexArr.join('');
			},
			/**
			 * 监听低功耗蓝牙设备的特征值变化事件。必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
			 */
			onBLECharacteristicValueChange() {
				// 必须在这里的回调才能获取
				uni.onBLECharacteristicValueChange(res => {
					console.log('监听低功耗蓝牙设备的特征值变化事件成功');
					// console.log(res);
					console.log(this.handShakeSetp);
					this.valueChangeData = res;
					let value = this.ab2hex(res.value);
					console.log("value=" + value.length + " -- " + value);
					if (value.length != 128) {
						if (this.handShakeSetp == 2) {
							if (value === "+OK\r\n") {
								this.handShakeSetp = 3;
								this.connected = true;
								console.log("三次握手成功，已确认设备可用！");
								this.saveStorage('Id', this.equipment[0].deviceId);
								this.saveStorage('Name', this.equipment[0].name);
								this.writeAData("+OK\r\n");
							} else if (this.handShakeCount++ > 3) {
								this.closeBLEConnection();
								this.handShakeSetp = 0;
								// this.connected = false;
								// this.equipment=[];
								uni.showToast({
									title: "此设备不支持"
								})
							}
							this.valueChangeData = {};
						} else if (this.handShakeSetp == 3) {
							let arrBuf = value.split(",");
							let recCount = parseInt(arrBuf[0]);
							if (recCount >= 0) {
								this.txtAnimate = this.txtAnis[recCount % 4];
								this.currentTemp = parseFloat(arrBuf[1]) / 10;
								if (!this.sliderChanging) this.setTemp = parseInt(arrBuf[2]) / 10; //当滑动温度条时，不允许更新设定温度
								let fired = (parseInt(arrBuf[3]) == 1) ? true : false;
								if (this.fired != fired) {
									this.fired = fired;
									if (this.fired) {
										// if (this.intervalID) clearInterval(this.intervalID);
										this.intervalID = setInterval(() => {
											this.fireAni = !this.fireAni;
										}, 400);
									} else {
										if (this.intervalID) clearInterval(this.intervalID);
										this.intervalID = 0;
									}
								}
							}
						}
					}
				});
			},
			// animateFire() {
			// 	this.fired = !this.fired;
			// },
			/**
			 * 订阅操作成功后需要设备主动更新特征值的 value，才会触发 uni.onBLECharacteristicValueChange 回调。
			 */
			notifyBLECharacteristicValueChange() {
				let deviceId = this.equipment[0].deviceId;
				let serviceId = this.sUUID;
				let characteristicId = this.cUUID;
				// let notify = this.cUUID.properties.notify;
				console.log(deviceId);
				console.log(serviceId);
				console.log(characteristicId);
				// console.log(notify);
				uni.notifyBLECharacteristicValueChange({
					state: true, // 启用 notify 功能
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId,
					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId,
					success(res) {
						console.log('notifyBLECharacteristicValueChange success:' + res.errMsg);
						console.log(JSON.stringify(res));
					}
				});
			},
			/**
			 * 监听低功耗蓝牙连接状态的改变事件。包括开发者主动连接或断开连接，设备丢失，连接异常断开等等
			 */
			onBLEConnectionStateChange() {
				uni.onBLEConnectionStateChange(res => {
					// 该方法回调中可以用于处理连接意外断开等异常情况
					console.log(`蓝牙连接状态 -------------------------->`);
					console.log(JSON.stringify(res));
					if (!res.connected) {
						if (this.isStop) return;
						console.log('断开低功耗蓝牙成功:');
						// this.$set(this.disabled, 1, false);
						// this.$set(this.disabled, 3, true);
						// this.$set(this.disabled, 4, true);
						// this.$set(this.disabled, 5, true);
						// this.$set(this.disabled, 6, true);
						// this.$set(this.disabled, 7, true);
						// this.$set(this.disabled, 8, true);
						// this.$set(this.disabled, 9, true);
						// this.searchLoad = false;
						// this.equipment = [];
						this.servicesData = [];
						this.characteristicsData = [];
						this.valueChangeData = {};
						// toast('不可识别的蓝牙设备，已经断开连接');
						this.closeBLEConnection();
						this.connected = false;
					}
				});
			},
			// 存储最近一次连接的设备
			saveStorage(key, value) {
				uni.setStorage({
					key: key,
					data: value,
					success: (res) => {
						console.log("存储成功");
					},
					fail: () => {
						console.log("存储失败");
					}
				})
			},
			loadStorage(key) {
				try {
					const value = uni.getStorageSync(key);
					if (value) {
						console.log(value);
						return value;
					}
				} catch (e) {
					// error
					return null;
				}
			}
		}
	}

	/**
	 * 判断初始化蓝牙状态
	 */
	function initTypes(code, errMsg) {
		switch (code) {
			case 10000:
				toast('未初始化蓝牙适配器');
				break;
			case 10001:
				toast('未检测到蓝牙，请打开蓝牙重试！');
				break;
			case 10002:
				toast('没有找到指定设备');
				break;
			case 10003:
				toast('连接失败');
				break;
			case 10004:
				toast('没有找到指定服务');
				break;
			case 10005:
				toast('没有找到指定特征值');
				break;
			case 10006:
				toast('当前连接已断开');
				break;
			case 10007:
				toast('当前特征值不支持此操作');
				break;
			case 10008:
				toast('其余所有系统上报的异常');
				break;
			case 10009:
				toast('Android 系统特有，系统版本低于 4.3 不支持 BLE');
				break;
			default:
				toast(errMsg);
		}
	}

	/**
	 * 弹出框封装
	 */
	function toast(content, showCancel = false) {
		uni.showModal({
			title: '提示',
			content,
			showCancel
		});
	}
</script>

<style>
	.view-image {
		text-align: center;
		font-size: 36rpx;
	}

	.image {
		mode: widthFix;
	}

	#image2 {
		height: 100rpx;
	}

	.view-slider {
		display: flex;
		flex-direction: row;
		font-size: 36rpx;
	}

	.uni-title {
		/* width: 100%; */
		/* height: 80rpx; */
		text-align: center;
	}

	.uni-mask {
		position: fixed;
		top: 0;
		left: 0;
		bottom: 0;
		display: flex;
		align-items: center;
		width: 100%;
		background: rgba(0, 0, 0, 0.6);
		padding: 0 30rpx;
		box-sizing: border-box;
	}

	.uni-scroll_box {
		height: 70%;
		background: #fff;
		border-radius: 20rpx;
	}

	.uni-list-box {
		margin: 0 20rpx;
		padding: 15rpx 0;
		border-bottom: 1px #f5f5f5 solid;
		box-sizing: border-box;
	}

	.uni-list_name {
		font-size: 30rpx;
		color: #333;
	}

	.uni-list_item {
		font-size: 24rpx;
		color: #555;
		line-height: 1.5;
	}

	.view-button {
		position: fixed;
		bottom: 2%;
		width: 60%;
		left: 20%;
	}
</style>
